Snackbar,是很常見的應用通知設計,位於應用程式的底部,提供用戶目前操作的任何相關訊息。由於 Snackbar 實作的篇幅較少,就一起講解
設計應用上,是用來通知用戶應用程序已經執行或將要執行的任務。會短暫出現在屏幕底部。不應該打斷用戶體驗,不需要用戶進行操作,時間到了會自動消失。而一次只能出現一個 Snacker Bars,過多的通知會讓使用者不知所措,沒辦法關注當前的事件
與 Snackbars 同為傳達用戶訊息的元件,還有兩個,分別為 Dialog、banner,下圖簡短的介紹一下。而 Snackbars 傳達的消息干擾最小且不需要用戶操作就會自動消失,不會阻擋用戶操作
Component | Priority | User action |
---|---|---|
Snackbar | low | 出現後再一定時間內會自動消失 |
banner | medium | 一直存在畫面,直到用戶關閉,或是當前的狀態導致它關閉 |
Dialog | highest | 會阻止當前應用程序的操作,直到用戶執行對 Dialog 的選項操作或退出 |
由於 Toast 與 Snackbar 在設計應用上非常相似,而在近期的應用程式中,我們也很少看到 Toast 的身影,雖然官方沒有明確的說 Snackbar 是來取代 Toast,但對用戶體驗上,很明顯 Snackbar 已經在慢慢取代 Toast,官方文檔有提到一些比較的內容,這邊我就簡單梳理幾點之間的差別
Snackbar Text的內容與要傳達的目的直接相關,例如 : 已刪除、更新資料,等等提醒用戶當前操作
其敘述應該要簡潔有力,最多出現到兩行大小。若是超過便會阻擋其他元件或是太過顯眼讓用戶失焦
而 Text Label 只當純呈現文字而已,不應該出現任何圖示或 icon,讓用戶解讀更加迷惑
Snackbars 會顯示在灰色背景的矩形 Container 中。應該完全不透明,讓 Text Label 保持可見
不應該有其他形狀的 Container 或是太過透明的顏色
也要記得加上 elevation ,讓它與原本的畫面層次不同,否則如下圖那樣,Snackbar 與 背景融在一起
Snackbars 只能有單個 Text Button,讓用戶可以對應用程序執行的進程執行操作。不應該讓 Action 擁有應用程式中太過重要的功能,通常只是對應當前情境的動作
Text Button 不應該使用與 Text label 相同顏色,或是使用 filled Button
若是在完成任務當下的 SnackBar,可以在 action 上設置 undo,讓用戶回溯當前的操作
在 action 設計上不用特定去設置關閉 Snackbar 的功能,因為它會自動消失,導致這種設計有點雞肋
Snackbars 會在沒有警告的情況下出現,而且不需要用戶與其互動。會在4 到 10 秒後自動從屏幕上消失
當需要多個 SnackBars 顯示時,應該依照順序出現,一次一個
所以應該避免如下的設計,一次出現多個 Snackbar
Snackbars 應放置在 UI 的底部,在應用程序內容的前面。避免在經常使用的 button、action 或 navigation 前面放置
避免放置在 navigation bottom 這種用戶常使用的操作 之上
僅當 UI 不使用 bottom bar 或 navigation 等持久的 navigation 組件時,Snackbars 才能跨越屏幕的整個寬度,但盡量避免。因為這樣的呈現方式,會讓用戶以為Snackbar 是與其他元件層級相同的
Snackbars 應該出現在 FABs 之上
避免出現兩者互蓋的情況,這會讓用戶無法正確操作到想要的功能
Snackbars 會永遠地直接出現在 footer elements (navigation bottom、bottom bar)上方
避免讓 Snackbar 出現在 footer element 下方,讓這些常駐的元件被迫移動
實作用都要透過編程的方式去呼叫,所以要客製元件屬性時,就會透過 method 來設置
透過 Snackbar 物件中的 make 方法,可以讓我們實作 Snackbar
Snackbar.make(binding.root,R.string.text_label, Snackbar.LENGTH_SHORT)
當中有三個參數要帶入
LENGTH_INDEFINITE
: 顯示直到被關閉,或是出現新的 SnackbarLENGTH_LONG
: 較長時間顯示LENGTH_SHORT
: 較短時間顯示若想為 SnackBar 添加功能,可以呼叫 setAction,來設定 action。當中的 Lambda 是一個 setOnClickLIstener,裡面可直接設定想要執行的功能
Snackbar.make(binding.root, "已完成刪除", Snackbar.LENGTH_SHORT)
.setAction("undo") {
// do something
}.show()
在預設情況下,Snackbar 的出現位置會依照,一開始在 make 帶入的 Parent View 參數的底部。如果當前的情境有 BottomBar or FABs 會阻檔到 Snackbar 出現位置的底部元件,要改變錨定的位置,使用 setAnchorView
Snackbar.make(...)
.setAnchorView(fab)
...
那除了上述能設置 AnchorView 與 Action 之外,還能去更改各種顏色或動畫
Snackbar.make(binding.root, "Custom in code", Snackbar.LENGTH_SHORT)
.setAnchorView(binding.bottomBtn)
.setAction("Action") {}
.setBackgroundTint(getColor(R.color.darkBlue))
.setTextColor(getColor(R.color.white))
.setActionTextColor(getColor(R.color.lightYellow))
.setAnimationMode(ANIMATION_MODE_SLIDE)
.show()
動畫的部分有 ANIMATION_MODE_SLIDE
, ANIMATION_MODE_FADE
兩種可選擇
在看完上述的屬性與組成後,我們只能透過 method or Style 去客製化 Snackbar。這邊就分兩個部分 in code , in style ,來看看能做到怎樣程度
就是剛剛介紹到 Customize 的部分,透過 method 去設置
Snackbar.make(binding.root, "Custom in code", Snackbar.LENGTH_SHORT)
.setAnchorView(binding.bottomBtn)
.setAction("Action") {}
.setBackgroundTint(getColor(R.color.lightYellow))
.setTextColor(getColor(R.color.white))
.setActionTextColor(getColor(R.color.tealBlue))
.setAnimationMode(ANIMATION_MODE_SLIDE)
.show()
我自定義的 style 設置了以下屬性,原本還有更多的,但因為設備上無法運行,所以目前有反應的只剩這幾個,不能更改的部分就是在 Text 與 ActionText,但這也可以在 code 當中去設定,所以也能混合應用,但如果擔心 style 在某些 project 中無法運行,建議還是都在編程中去設定
<style name="ThemeOverlay.App.SnackBar" parent="">
<!-- SnackBar backgroundTint -->
<item name="colorOnSurface">@color/black</item>
</style>
<style name="Widget.App.Snackbar" parent="Widget.MaterialComponents.Snackbar">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.SnackBar</item>
<item name="animationMode">slide</item>
<item name="actionTextColorAlpha">0.6</item>
</style>
Snackbar 是個常見且簡單的元件。設計上,注重在與畫面交互的呈現方式,雖然一貫上是放在下方,但多少會與 FABs , Navigation Bottom 等底部元件衝突,在配置上也需要注意。色彩上,也必須與不同畫面之間有所區別,讓用戶能準確看到
實作上,由於是綁定系統的設置,所以能改動的部分大多是在顏色上面,只能透過 style or method 來改變
若對實作還是有點不懂的,這邊提供我的 Github 方便大家參考